home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 18 / CU Amiga Magazine's Super CD-ROM 18 (1997)(EMAP Images)(GB)[!][issue 1998-01].iso / CUCD / Online / hsc / source / ugly / args_prp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-02  |  13.1 KB  |  467 lines

  1. /*
  2.  * This source code is part of hsc, a html-preprocessor,
  3.  * Copyright (C) 1993-1997  Thomas Aglassinger
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  */
  20. /*
  21.  * ugly/args_prp.c
  22.  *
  23.  * ugly argument preparation functions
  24.  *
  25.  * Copyright (C) 1994,95,96  Thomas Aglassinger
  26.  *
  27.  * This program is free software; you can redistribute it and/or modify
  28.  * it under the terms of the GNU General Public License as published by
  29.  * the Free Software Foundation; either version 2 of the License, or
  30.  * (at your option) any later version.
  31.  *
  32.  * This program is distributed in the hope that it will be useful,
  33.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  34.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  35.  * GNU General Public License for more details.
  36.  *
  37.  * You should have received a copy of the GNU General Public License
  38.  * along with this program; if not, write to the Free Software
  39.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  40.  *
  41.  * updated: 15-Nov-1996
  42.  * created:  3-Jul-1994
  43.  *
  44.  *===================================================================
  45.  * TODO:
  46.  * - free all memory in error case
  47.  *
  48.  */
  49.  
  50. /*
  51.  * includes
  52.  */
  53. #include <stdio.h>
  54. #include <stdlib.h>
  55. #include <stdarg.h>
  56. #include <string.h>
  57. #include <ctype.h>
  58.  
  59. #include "utypes.h"
  60. #include "umemory.h"
  61. #include "ustring.h"
  62. #include "dllist.h"
  63.  
  64. #define NOEXTERN_UGLY_UARGS_H
  65. #include "uargs.h"
  66.  
  67. /*
  68.  * error vars
  69.  */
  70. LONG prep_error_num;            /* error number */
  71. int prep_error_idx;             /* # of template causing error */
  72. size_t prep_error_pos;          /* pos in arg */
  73. BOOL no_preperr, any_preperr;   /* error flags for _prepare_args() */
  74.  
  75. /*
  76.  * error functions for _prepare_arg()
  77.  *
  78.  */
  79. void set_preperr(LONG num, size_t pos)
  80. {
  81.     if (no_preperr)
  82.     {
  83.  
  84.         no_preperr = FALSE;
  85.         any_preperr = TRUE;
  86.         prep_error_num = num;
  87.         prep_error_pos = pos;
  88.  
  89.     }
  90. }
  91.  
  92. void clr_preperr(void)
  93. {
  94.     no_preperr = TRUE;
  95.     any_preperr = FALSE;
  96.     prep_error_num = 0;
  97.     prep_error_pos = 0;
  98. }
  99.  
  100. /*
  101.  * fprintf_arginfo (debugging aid)
  102.  */
  103. void fprintf_arginfo(FILE * stream, APTR data)
  104. {
  105.     struct arginfo *arg = (struct arginfo *) data;
  106.  
  107.     fprintf(stream, "  %-15s %2lx %2lx",
  108.             arg->ai_id, arg->ai_type, arg->ai_flags);
  109.     if (arg->ai_help)
  110.         printf("  \"%s\"", arg->ai_help);
  111.     fprintf(stream, "\n");
  112. }
  113.  
  114. /*
  115.  * prepare_args
  116.  *
  117.  * convert argument definitions to dllist of struct arginfo
  118.  *
  119.  */
  120. struct arglist *prepare_args(STRPTR arglist_name,...)
  121. {
  122.     va_list ap;
  123.     struct dllist *newlist;
  124.     struct arginfo *newarg;
  125.     struct arglist *new_arglist = NULL;
  126.  
  127.     DA(fprintf(stderr, DUA "prepare_args()\n"));
  128.  
  129.     clr_preperr();              /* clear error vars */
  130.  
  131.     /*
  132.      * alloc & init _new_arglist
  133.      */
  134.     new_arglist = (struct arglist *)
  135.         umalloc(sizeof(struct arglist));
  136.  
  137.     if (new_arglist)
  138.     {
  139.  
  140.         new_arglist->al_name = arglist_name;
  141.         new_arglist->al_list = NULL;
  142.         new_arglist->al_multiple = NULL;
  143.         new_arglist->al_nokeywd = NULL;
  144.  
  145.     }
  146.     else
  147.         set_preperr(APE_NO_MEM, 0);
  148.  
  149.     /*
  150.      * TODO: don't go into if(), when new_arglist failed
  151.      */
  152.  
  153.     /*
  154.      * convert template to double linked list
  155.      */
  156.     newlist = init_dllist(del_arginfo);
  157.  
  158.     if (newlist)
  159.     {
  160.  
  161.         STRPTR nxtdef = NULL;   /* next template definition */
  162.  
  163.         va_start(ap, arglist_name);
  164.  
  165.         do
  166.         {
  167.  
  168.             ufreestr(nxtdef);
  169.             nxtdef = va_arg(ap, STRPTR);        /* get next definition */
  170.  
  171.             /* clone nxtdef: this is necessary because on unix-systems, */
  172.             /* you can not let strtok() run on strings received with    */
  173.             /* va_arg() -> bus error                                    */
  174.             nxtdef = strclone(nxtdef);
  175.             prep_error_idx++;
  176.  
  177.             if (nxtdef)
  178.             {
  179.  
  180.                 DA(fprintf(stderr, DUA "  `%s'\n", nxtdef));
  181.  
  182.                 newarg = umalloc(sizeof(struct arginfo));
  183.  
  184.                 if (newarg)
  185.                 {
  186.  
  187.                     STRPTR new_id;
  188.                     STRPTR typestr;
  189.                     STRPTR flagstr = NULL;
  190.                     STRPTR enumstr = NULL;      /* enum string for type 'E' */
  191.                     LONG new_type = 0;
  192.                     LONG new_flags = 0;
  193.                     LONG rnlolim = 0;
  194.                     LONG rnhilim = 0;
  195.  
  196.                     /* init _newarg */
  197.                     newarg->ai_id = NULL;
  198.                     newarg->ai_type = 0;
  199.                     newarg->ai_flags = 0;
  200.                     newarg->ai_misc1.ai_lolim = 0;
  201.                     newarg->ai_misc2.ai_uplim = 0;
  202.                     newarg->ai_dest = NULL;
  203.                     newarg->ai_func = NULL;
  204.                     newarg->ai_help = NULL;
  205.  
  206.                     new_id = strtok(nxtdef, "/");
  207.  
  208.                     typestr = strtok(NULL, "/");
  209.  
  210.                     /*
  211.                      * get argument type
  212.                      */
  213.                     if (typestr)
  214.                     {
  215.  
  216.                         if (strlen(typestr) == 1)
  217.                         {
  218.  
  219.                             switch (toupper(typestr[0]))
  220.                             {
  221.  
  222.                             case 'T':
  223.                                 new_type = ARG_TEXT;
  224.                                 break;
  225.  
  226.                             case 'S':
  227.                                 new_type = ARG_SWITCH;
  228.                                 break;
  229.  
  230.                             case 'N':
  231.                                 new_type = ARG_LONG;
  232.                                 break;
  233.  
  234.                             case 'R':
  235.                                 new_type = ARG_LONG_RANGE;
  236.                                 break;
  237.  
  238.                             case 'E':
  239.                                 new_type = ARG_ENUM;
  240.                                 break;
  241.  
  242.                             }
  243.  
  244.                             if (new_type)       /* arg-type specified? */
  245.                                 flagstr =       /* Y-> get next flag */
  246.                                     strtok(NULL, "/");
  247.                             else
  248.                             {
  249.  
  250.                                 flagstr = typestr;      /* N-> must be flag */
  251.                                 new_type = ARG_TEXT;    /*     set type to text */
  252.  
  253.                             }
  254.  
  255.                         }
  256.                         else
  257.                             set_preperr(APE_INVALID_TEMPLATE, 0);
  258.  
  259.                     }
  260.                     else
  261.                     {           /* no type at all */
  262.  
  263.                         flagstr = NULL;         /* -> no flags also */
  264.                         new_type = ARG_TEXT;    /*    set type to text */
  265.  
  266.                     }           /* if typestr */
  267.  
  268.                     /*
  269.                      * get argument flags
  270.                      */
  271.                     while (flagstr && flagstr[0] && no_preperr)
  272.                     {
  273.  
  274.                         switch (toupper(flagstr[0]))
  275.                         {
  276.  
  277.                         case 'M':
  278.                             new_flags |= ARG_MULTIPLE;
  279.                             break;
  280.  
  281.                         case 'A':
  282.                             new_flags |= ARG_REQUIRED;
  283.                             break;
  284.  
  285.                         case 'K':
  286.                             new_flags |= ARG_KEYWORD;
  287.                             break;
  288.  
  289.                         case 'O':
  290.                             new_flags |= ARG_OVERWRITE;
  291.                             break;
  292.  
  293.                         case '$':
  294.                             new_flags |= ARG_HANDLEFUNC;
  295.                             break;
  296.  
  297.                         default:
  298.                             set_preperr(APE_ILLEGAL_FLAG, 0);
  299.                             break;
  300.  
  301.                         }       /* switch */
  302.  
  303.                         flagstr = strtok(NULL, "/");
  304.  
  305.                     }           /* while */
  306.  
  307.                     if (no_preperr)
  308.                     {
  309.  
  310.                         /*
  311.                          * get additional arguments
  312.                          */
  313.                         if (new_flags & ARG_HANDLEFUNC)
  314.                         {
  315.  
  316.                             /*
  317.                              * get handler function
  318.                              */
  319. #if 1
  320.                             APTR func_tmp = va_arg(ap, STRPTR);
  321.                             newarg->ai_func = (STRPTR(*)(STRPTR)) func_tmp;
  322. #else
  323.                             /* tricky type-cast, 1-step-version, does */
  324.                             /* not work with several compilers */
  325.                             newarg->ai_func = va_arg(ap, STRPTR(*)(STRPTR));
  326. #endif
  327.  
  328.                         }
  329.  
  330.                         if (new_type == ARG_LONG_RANGE)
  331.                         {
  332.  
  333.                             /*
  334.                              * get range limits
  335.                              */
  336.                             rnlolim = va_arg(ap, LONG);
  337.                             rnhilim = va_arg(ap, LONG);
  338.  
  339.                         }
  340.                         else if (new_type == ARG_ENUM)
  341.                         {
  342.  
  343.                             /*
  344.                              * get enum string
  345.                              */
  346.                             enumstr = va_arg(ap, STRPTR);
  347.  
  348.                         }
  349.  
  350.                         if (no_preperr)
  351.                         {
  352.  
  353.                             newarg->ai_id = strclone(new_id);   /* sux */
  354.                             newarg->ai_type = new_type;
  355.                             newarg->ai_flags = new_flags;
  356.                             newarg->ai_dest = va_arg(ap, APTR);
  357.                             newarg->ai_help =
  358.                                 strclone(va_arg(ap, STRPTR));
  359.  
  360.                             /*
  361.                              * set additional argument information
  362.                              * (->misc1, ->misc2)
  363.                              */
  364.                             switch (new_type)
  365.                             {
  366.  
  367.                             case ARG_ENUM:
  368.                                 newarg->ai_misc1.ai_enum = strclone(enumstr);
  369.                                 if (!(newarg->ai_misc1.ai_enum))
  370.                                     set_preperr(APE_NO_MEM, 0);
  371.                                 break;
  372.  
  373.                             case ARG_LONG_RANGE:
  374.                                 newarg->ai_misc1.ai_lolim = rnlolim;
  375.                                 newarg->ai_misc2.ai_uplim = rnhilim;
  376.                                 break;
  377.  
  378.                             }
  379.  
  380.                             /*
  381.                              * check for NULL as destination var
  382.                              */
  383.                             if (newarg->ai_dest == NULL)
  384.                                 set_preperr(APE_DESTVAR_IS_NULL, 0);
  385.  
  386.                         }
  387.  
  388.                         /*
  389.                          * check, if arg multiple arg without keyword
  390.                          */
  391.                         if (new_flags & ARG_MULTIPLE)
  392.                             if (!(new_flags & ARG_KEYWORD))
  393.                                 if (new_arglist->al_multiple)
  394.                                     set_preperr(APE_DOUBLE_MULTIPLE, 0);
  395.                                 else
  396.                                     new_arglist->al_multiple = newarg;
  397.  
  398.                         /*
  399.                          * append new argument entry to list
  400.                          */
  401.                         if (no_preperr)
  402.                             if (app_dlnode(newlist, (APTR) newarg)
  403.                                 == NULL)
  404.                                 set_preperr(APE_NO_MEM, 0);
  405.  
  406.                         /* free _newarg if any error occured */
  407.                         if (any_preperr)
  408.                             del_arginfo((APTR) newarg);
  409.  
  410.                     }
  411.  
  412.                 }
  413.                 else
  414.                     set_preperr(APE_NO_MEM, 0);
  415.  
  416.             }
  417.             else
  418.             {
  419.  
  420.                 DA(fprintf(stderr, DUA "  (end prepare)\n"));
  421.  
  422.             }
  423.  
  424.         }
  425.         while (nxtdef && no_preperr);
  426.  
  427.         /* free last value of nxtdef */
  428.         ufreestr(nxtdef);
  429.  
  430. #if 0
  431.         while (nxtdef)          /* flush arguments */
  432.             nxtdef = va_arg(ap, STRPTR);        /* (in error case) */
  433. #endif
  434.         va_end(ap);
  435.  
  436.     }
  437.     else
  438.         set_preperr(APE_NO_MEM, 0);
  439.  
  440.     /*
  441.      * check for empty template
  442.      */
  443.     if (no_preperr)
  444.         if (newlist->first == NULL)
  445.             set_preperr(APE_EMPTY_TEMPLATE, 0);
  446.  
  447.     /*
  448.      * free newlist, if any error occured
  449.      */
  450.     if (any_preperr)
  451.     {
  452.  
  453.         /* free newlist */
  454.         del_dllist(newlist);
  455.         ufree(new_arglist);
  456.         newlist = NULL;
  457.         new_arglist = NULL;
  458.  
  459.     }
  460.     else
  461.         new_arglist->al_list = newlist;
  462.  
  463.     return new_arglist;
  464.  
  465. }
  466.  
  467.